package com.opennews.openplatform.myspringbootcore.util

import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.core.JsonToken
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.JsonSerializer
import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.databind.annotation.JsonSerialize

@JsonSerialize(using = IdFieldSerializer::class)
@JsonDeserialize(using = IdFieldDeserializer::class)
sealed class IdField {
    abstract fun asLong(): Long
    abstract fun asString(): String

    data class Text(val value: String) : IdField() {
        override fun asLong(): Long =
            value.toLongOrNull() ?: error("IdField.Text cannot be converted to Long: '$value'")

        override fun asString(): String = value
    }

    data class Number(val value: Long) : IdField() {
        override fun asLong(): Long = value
        override fun asString(): String = value.toString()
    }
}

class IdFieldSerializer : JsonSerializer<IdField>() {
    override fun serialize(
        field: IdField?,
        generator: JsonGenerator?,
        serializer: SerializerProvider?,
    ) {
        when (field) {
            is IdField.Text -> generator?.writeString(field.value)
            is IdField.Number -> generator?.writeNumber(field.value)
            else -> generator?.writeNull()
        }
    }
}

class IdFieldDeserializer : JsonDeserializer<IdField>() {
    override fun deserialize(
        parser: JsonParser?,
        context: DeserializationContext?,
    ): IdField? {
        return when (parser?.currentToken) {
            JsonToken.VALUE_STRING -> IdField.Text(parser.text)
            JsonToken.VALUE_NUMBER_INT -> IdField.Number(parser.longValue)
            else -> null
        }
    }
}